using Engine;

namespace SCIENEW {
    public class PipeFluidConnection(HashSet<FluidTransferrer> fromTransferrers, HashSet<FluidTransferrer> toTransferrers, HashSet<FluidConnector> fromConnectors, HashSet<FluidConnector> toConnectors, float rate, Type transferringType, SubsystemFluidTransfer subsystemFluidTransfer) {
        public HashSet<FluidTransferrer> FromTransferrers = fromTransferrers;
        public HashSet<FluidTransferrer> ToTransferrers = toTransferrers;
        public HashSet<FluidConnector> FromConnectors = fromConnectors;
        public HashSet<FluidConnector> ToConnectors = toConnectors;
        public float Rate = rate;
        public Type TransferringType = transferringType;
        public SubsystemFluidTransfer SubsystemFluidTransfer = subsystemFluidTransfer;

        public bool IsTransferring { get; protected set; } = false;
        public int? TransferringFluid { get; protected set; } = null;

        /// <summary>
        /// 更新连接的输送速率
        /// </summary>
        public virtual void UpdateRate() {
            foreach (var connector in fromConnectors) {
                Rate = MathF.Min(Rate, connector.Rate);
            }
            foreach (var connector in toConnectors) {
                Rate = MathF.Min(Rate, connector.Rate);
            }
        }

        public virtual Vector3 CalcAveragePosition() {
            Vector3 vector = Vector3.Zero;
            foreach (var transferrer in fromTransferrers) {
                vector += new Vector3(transferrer.Position);
            }
            foreach (var transferrer in toTransferrers) {
                vector += new Vector3(transferrer.Position);
            }
            vector /= fromTransferrers.Count + toTransferrers.Count;
            return vector + new Vector3(0.5f);
        }

        public virtual void Init() {

        }

        /// <summary>
        /// 接口的模拟：从一端移除液体，接入另一端
        /// </summary>
        /// <param name="dt"></param>
        public virtual void Simulate(float dt) {
            IsTransferring = false;

            if (toTransferrers.Any(x => x.GetTank() == null) || fromTransferrers.Any(x => x.GetTank() == null)) return;
            // 确保目标端有足够的空间接受液体
            if (toTransferrers.All(x => x.IsFull(x.GetTank()))) return;


            float volume = Rate * dt; // 计算在给定时间段内应转移的液体体积

            // 确定要转移的液体类型
            TransferringFluid = null;
            foreach (var fromTransferrer in fromTransferrers) {
                if (TransferringFluid != null) break;

                int fromFluidValue = fromTransferrer.GetFluidValue(fromTransferrer.GetTank());
                if (FluidsManager.GetFluid(fromFluidValue).GetType().GetInterfaces().Contains(transferringType)) {
                    TransferringFluid = fromFluidValue;
                }
            }
            if (TransferringFluid == null) return;

            //从源中移除液体
            float totalRemovedVolume = 0;
            int removedTankCount = 0;
            foreach (var fromTransferrer in fromTransferrers) {
                ITank fromTank = fromTransferrer.GetTank();
                //检查源中液体类型是否匹配
                int fromValue = fromTransferrer.GetFluidValue(fromTank);
                if (fromValue != TransferringFluid) continue;

                //移除液体
                fromTransferrer.RemoveFluid(fromTank, volume, out float removedVolume, out _);
                totalRemovedVolume += removedVolume;
                removedTankCount++;
            }

            IsTransferring = totalRemovedVolume > 0;

            //添加液体到需中
            foreach (var toTransferrer in toTransferrers) {
                if (totalRemovedVolume <= 0) break;//取出的液体分配完了，结束

                ITank toTank = toTransferrer.GetTank();
                float unitVolume = totalRemovedVolume / ((float)toTransferrers.Count / removedTankCount);//保证水平均分配
                float remainVolume = MathF.Max(0, toTransferrer.AcquireFluid(toTank, unitVolume, TransferringFluid.Value));
                float acquiredVolume = unitVolume - remainVolume;
                totalRemovedVolume -= acquiredVolume;
            }

            //返还多余的液体
            foreach (var fromTransferrer in fromTransferrers) {
                if (totalRemovedVolume <= 0) break;

                ITank fromTank = fromTransferrer.GetTank();
                totalRemovedVolume = fromTransferrer.AcquireFluid(fromTank, totalRemovedVolume, TransferringFluid.Value);
            }
        }
    }
}